home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
tsh10.zip
/
TSH.C
< prev
next >
Wrap
Text File
|
1994-07-03
|
44KB
|
2,221 lines
/*
* tsh - "Troy's Shell" - a command line interface for Windows.
*
* Copyright (C) 1994 Troy Rollo <troy@cbme.unsw.EDU.AU>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <dir.h>
#include <dos.h>
#include <sys/stat.h>
#include <io.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <toolhelp.h>
#include <share.h>
#include <sys/tkwin.h>
#include <sys/tkern.h>
#include <sys/tkexec.h>
#include <sys/task.h>
#include <sys/wait.h>
#include <signal.h>
char *Months[] =
{
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
char *Days[] =
{
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
struct redirection
{
int fd;
int fdSource;
int iMode;
char *pchFile;
};
struct backend
{
int iTask;
struct backend *pbeNext;
};
struct backend *pbeList = 0;
int parse_command(char const *s);
char *pwd(void);
static char tmpbuf[2048];
static char buf[2048] = {0};
static char title[80] = "tsh";
static unsigned instance = 0;
static HWND hWnd = 0;
static HWND hWndOA;
static HINSTANCE hInstance;
static HTASK hTask;
static BOOL bBreak = FALSE;
#pragma argsused
BOOL CALLBACK _export EnumOldApp(HWND hThisWnd, LPARAM lParam)
{
hWndOA = hThisWnd;
return TRUE;
}
HTASK GetTaskFromInstance(HINSTANCE hInst)
{
TASKENTRY te;
te.dwSize = sizeof(TASKENTRY);
TaskFirst(&te);
do
{
if (te.hInst == hInst)
return te.hTask;
} while (TaskNext(&te));
return 0;
}
HINSTANCE GetInstanceFromTask(HTASK hTask)
{
TASKENTRY te;
te.dwSize = sizeof(TASKENTRY);
TaskFirst(&te);
do
{
if (te.hTask == hTask)
return te.hInst;
} while (TaskNext(&te));
return 0;
}
char *BaseName(char *File)
{
char *c1;
char *c2;
c1 = strrchr(File, '\\');
c2 = strrchr(File, '/');
if (c1 || c2)
{
if (c1 > c2)
return c1+1;
else
return c2+1;
}
return File;
}
#define MAXTASKS 20
char WhiteSpace[] = " \t";
char EmptyString[] = "";
struct TaskInfo
{
HTASK hTask;
WORD wStatus;
};
#define EF_BATCH 0x0001
struct ExtTypes
{
char Ext[4];
char Prog[13];
int Exists;
int Flags;
} Extensions[80] =
{
"EXE", "", 0, 0,
"COM", "", 0, 0,
"TSH", "*", 0, EF_BATCH,
"BAT", "", 0, 0,
"PIF", "", 0, 0,
"", "", 0, 0
};
BOOL NewDead = FALSE;
struct TaskInfo Tasks[MAXTASKS];
void FlushMessages(void)
{
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
int cmdnum = 0;
char *prompt_names[3] = { "PS1", "PS2", "PS3" };
void PutFormat(char *buffer, char const *format)
{
char *c;
char const *tmp;
char varname[20];
c = buffer;
for (;*format;format++)
{
switch(*format)
{
case '!':
sprintf(c, "%d", cmdnum);
c+=strlen(c);
break;
case '~':
strcpy(c, pwd());
c+=strlen(c);
break;
case '$':
if (format[1]!='{')
break;
tmp = ++format;
while (*format && *format != '}')
format++;
if (!*format)
{
format--;
break;
}
strncpy(varname, tmp, format-tmp);
varname[format-tmp] = '\0';
if ((tmp = getenv(varname)) != 0)
{
strcpy(c, tmp);
c+=strlen(c);
}
break;
default:
*c++ = *format;
break;
}
}
*c = '\0';
}
void
add_backend(int iTask)
{
struct backend **ppbe;
for (ppbe = &pbeList; *ppbe; ppbe = &(*ppbe)->pbeNext);
*ppbe = (struct backend *) malloc(sizeof(struct backend));
(*ppbe)->iTask = iTask;
(*ppbe)->pbeNext = 0;
}
BOOL
remove_backend(int iTask)
{
struct backend **ppbe, *pbeTemp;
for (ppbe = &pbeList; *ppbe; ppbe = &(*ppbe)->pbeNext)
{
if ((*ppbe)->iTask == iTask)
{
pbeTemp = *ppbe;
*ppbe = pbeTemp->pbeNext;
free(pbeTemp);
return TRUE;
}
}
return FALSE;
}
void show_prompt(int number)
{
char *format;
char buffer[160];
char *c;
char *tmp;
char varname[20];
struct time timeval;
long dateval;
struct tm *gmt;
c = buffer;
if ((format = getenv(prompt_names[number])) != 0)
{
PutFormat(buffer, format);
}
else
{
format = getenv("PROMPT");
for (;*format;format++)
{
if (*format == '$')
{
switch(*++format)
{
case 'p':
strcpy(c, pwd());
c+=strlen(c);
break;
case 'q':
*c++ = '=';
break;
case '$':
*c++ = '$';
break;
case 't':
gettime(&timeval);
sprintf(c, "%02d:%02d:%02d.%02d",
timeval.ti_hour,
timeval.ti_min,
timeval.ti_sec,
timeval.ti_hund);
c += strlen(c);
break;
case 'd':
time(&dateval);
gmt = gmtime(&dateval);
sprintf(c, "%3.3s %02d-%02d-%04d",
Days[gmt->tm_wday],
gmt->tm_mon+1,
gmt->tm_mday,
gmt->tm_year+1900);
c += strlen(c);
break;
case 'v':
sprintf(c, "MS-DOS Version %d.%d", _osmajor, _osminor);
c += strlen(c);
break;
case 'l':
*c++ = '<';
break;
case 'g':
*c++ = '>';
break;
case 's':
*c++ = ';';
break;
case 'c':
*c++ = ':';
break;
case 'r':
*c++ = '\r';
break;
case '_':
*c++ = '\n';
break;
case 'n':
*c++ = 'A' + getdisk();
break;
case 'b':
*c++ = '|';
break;
case 'e':
*c++ = '\033';
break;
case 'h':
*c++ = '\b';
break;
case '!':
sprintf(c, "%d", cmdnum);
c+=strlen(c);
break;
case '\0':
format--;
}
}
else
(*c++ = *format);
}
*c = '\0';
}
printf("%s", buffer);
if (hWnd && (format = getenv("WS1")) != 0)
{
PutFormat(buffer, format);
SetWindowText(hWnd, buffer);
}
}
#pragma argsused
void
IntCatcher(int nSig)
{
bBreak = TRUE;
signal(SIGINT, IntCatcher);
}
#pragma argsused
main(int argc, char **argv)
{
int i;
FILE *fp;
long wstatus;
short pid;
hTask = GetCurrentTask();
hInstance = GetInstanceFromTask(hTask);
for (i = 0; i<MAXTASKS; i++)
Tasks[i].hTask = 0;
if (tkern_is_device(0, "window"))
hWnd = (HWND) ioctl(0, WIOCGETHANDLE);
signal(SIGINT, IntCatcher);
if ((fp = fopen("C:\\AUTOEXEC.TSH", "r")) != 0)
{
while (!bBreak && fgets(buf, 2048, fp))
{
buf[strlen(buf)-1] = '\0';
parse_command(buf);
}
fclose(fp);
}
while(1)
{
++cmdnum;
while ((pid = waitpid(0, &wstatus , WNOHANG)) > 0)
{
if (remove_backend(pid))
;
else if (WIFEXITED(wstatus))
printf("%d - Exit %d\n",
(int) pid,
(int) WEXITSTATUS(wstatus));
else if (WIFSTOPPED(wstatus))
printf("%d - Stopped\n",
(int) pid);
else
printf("%d - Terminated (Signal %d)\n",
(int) pid,
(int) WTERMSIG(wstatus));
}
if (bBreak)
{
printf("\nInterrupt\n");
bBreak = FALSE;
}
show_prompt(0);
if (bBreak)
bBreak = FALSE;
if (!gets(buf))
break;
if (bBreak)
bBreak = FALSE;
parse_command(buf);
}
return 0;
}
#pragma argsused
char *pwd(void)
{
static char buf[256];
char *s;
return ((s = getcwd(buf, 255)) != 0) ? s : "invalid";
}
#pragma argsused
int do_pwd(int argc, char **argv)
{
printf("Current directory is %s\n", pwd());
return 0;
}
int do_chdrive(char *s)
{
if (islower(*s))
*s=toupper(*s);
if (s[1] == ':')
{
setdisk(s[0] - 'A');
return 0;
}
else
{
return 1;
}
}
int do_cd(int argc, char **argv)
{
if (argc != 1)
{
printf("Usage: cd directory\n");
return 1;
}
if (argv[0][1] == ':')
{
// allow drives in here too
if (do_chdrive(argv[0]))
return 2;
argv[0] += 2;
}
if (*argv[0] && chdir(argv[0]))
{
printf("File not found\n");
return 3;
}
else
return 0;
}
#define DF_LONG 1
#define DF_SIZE 2
#define DF_ALL 4
#define DF_PC 8
#define DF_DIRONLY 16
#define DF_SPC 32
#define DF_RECUR 64
#define DF_DOS 128
void show_filename(char *directory, struct find_t *pinfo, unsigned Flags, unsigned FileNo)
{
struct stat sbuf;
char attributes[8];
char *c, *c2;
struct tm *modtime;
char path[256];
char specialc;
strcpy(path, directory);
if (path[0] && path[strlen(path) - 1] != '\\')
strcat(path, "\\");
strcat(path, pinfo->name);
stat(path, &sbuf);
c=attributes;
specialc = ' ';
switch(sbuf.st_mode&S_IFMT)
{
case S_IFDIR:
*c++='d';
specialc = '/';
break;
case S_IFIFO:
*c++='p';
break;
case S_IFCHR:
*c++='c';
break;
case S_IFBLK:
*c++='b';
break;
default:
*c++='-';
break;
}
modtime = localtime(&sbuf.st_mtime);
*c++=(sbuf.st_mode&S_IREAD)?'r':'-';
if ((sbuf.st_mode&S_IFMT) == S_IFDIR)
*c++ = 'w';
else
*c++=(sbuf.st_mode&S_IWRITE)?'w':'-';
if ((c2 = strrchr(pinfo->name, '.')) != 0 &&
!(strcmp(c2+1, "EXE") &&
strcmp(c2+1, "COM") &&
strcmp(c2+1, "BAT") &&
strcmp(c2+1, "DIR") &&
strcmp(c2+1, "TEX") &&
strcmp(c2+1, "TCO") &&
strcmp(c2+1, "TSH")))
{
specialc = '*';
*c++ = 'x';
}
else
*c++=(sbuf.st_mode&S_IEXEC)?'x':'-';
*c++=(pinfo->attrib & _A_SYSTEM)?'s':'-';
*c++=(pinfo->attrib & _A_HIDDEN)?'h':'-';
*c++=(pinfo->attrib & _A_ARCH)?'a':'-';
*c='\0';
if (!(sbuf.st_mode&S_IFDIR))
for (c=pinfo->name; *c; c++)
if (isupper(*c))
*c=tolower(*c);
if (!(Flags & DF_PC))
specialc = ' ';
if (Flags & DF_DOS)
{
if (sbuf.st_mode&S_IFDIR)
{
printf("%-12s <DIR> %2d-%02d-%02d %02d:%02d%c\n",
pinfo->name, modtime->tm_mon+1, modtime->tm_mday,
modtime->tm_year,
(modtime->tm_hour==0)?12:(
(modtime->tm_hour<12)?modtime->tm_hour:(modtime->tm_hour-12)),
modtime->tm_min, (modtime->tm_hour<12)?'a':'p');
}
else
{
printf("%-12s %9ld %2d-%02d-%02d %02d:%02d%c\n",
pinfo->name, pinfo->size,
modtime->tm_mon+1, modtime->tm_mday,
modtime->tm_year,
(modtime->tm_hour==0)?12:(
(modtime->tm_hour<12)?modtime->tm_hour:(modtime->tm_hour-12)),
modtime->tm_min, (modtime->tm_hour<12)?'a':'p');
}
}
else if (Flags & DF_LONG)
{
printf(" %s %8ld %2d-%3.3s-%2.2d %02d:%02d %s%c\n",
attributes, pinfo->size,
modtime->tm_mday, Months[modtime->tm_mon], modtime->tm_year,
modtime->tm_hour, modtime->tm_min, pinfo->name, specialc);
}
else
{
printf("%s%c%*.*s", pinfo->name, specialc,
14-strlen(pinfo->name), 14-strlen(pinfo->name), " ");
if (FileNo%5 == 4)
putchar('\n');
}
}
void list_file(char *name, unsigned Flags)
{
char dirname[80];
char wildcard[80];
unsigned attrib;
unsigned files;
unsigned long bytes;
struct find_t info;
struct stat sbuf;
strcpy(dirname, name);
*BaseName(dirname) = '\0';
strcpy(wildcard, name);
if (strlen(wildcard) == 2 && wildcard[1] == ':')
strcat(wildcard, ".");
attrib = _A_NORMAL | _A_SUBDIR | _A_RDONLY;
if (Flags & DF_ALL)
attrib |= _A_SYSTEM | _A_HIDDEN;
if (!(Flags&DF_DIRONLY) &&
!strchr(wildcard, '?') &&
!strchr(wildcard, '*') &&
stat(wildcard, &sbuf) != -1 &&
(sbuf.st_mode & S_IFMT) == S_IFDIR)
{
if (wildcard[strlen(wildcard)-1] != '\\')
{
strcat(wildcard, "\\");
strcpy(dirname, wildcard);
}
strcat(wildcard, "*.*");
}
files = 0;
if (_dos_findfirst(wildcard, attrib, &info) != 0)
{
printf("%s: File Not Found\n", wildcard);
return;
}
files = 0;
bytes = 0;
do
{
if (*info.name == '.' && !(Flags&DF_SPC))
continue;
show_filename(dirname, &info, Flags, files);
files++;
bytes += info.size;
} while (!bBreak && _dos_findnext(&info) == 0);
if (!(Flags & (DF_DOS | DF_LONG)) && (files % 5))
putchar('\n');
printf("%5u File(s)\t%lu bytes\n", files, bytes);
return;
}
int do_std_dir(int argc, char **argv, unsigned Flags)
{
struct find_t info;
unsigned long bytes;
unsigned attrib, files;
char *arg;
struct stat sbuf;
while (argc && **argv == '-')
{
argc--;
arg = *argv++;
while (*++arg)
{
switch(*arg)
{
case 'l':
Flags |= DF_LONG;
break;
case 'a':
Flags |= DF_ALL | DF_SPC;
break;
case 'A':
Flags |= DF_ALL;
break;
case 's':
Flags |= DF_SIZE;
break;
case 'C':
break; /* No op */
case 'd':
Flags |= DF_DIRONLY;
break;
case 'F':
Flags |= DF_PC;
break;
case 'R':
Flags |= DF_RECUR;
break;
case 'D':
Flags |= DF_DOS;
break;
case 'W':
case 'w':
Flags &= ~DF_DOS;
default:
fprintf(stderr, "Usage: ls [-laAsCdFRDwW] [directories]\n");
return 1;
}
}
}
if (argc)
{
while (argc--)
list_file(*argv++, Flags);
}
else
list_file(".", Flags);
return 0;
}
int do_dir(int argc, char **argv)
{
return do_std_dir(argc, argv, 0);
}
int do_dos_dir(int argc, char **argv)
{
return do_std_dir(argc, argv, DF_DOS);
}
int do_df(int argc, char **argv)
{
struct diskfree_t dtable;
char drive;
long nKbytes;
printf("Drive CSize Total Free KB Free %%Used\n");
if (argc)
{
while (argc--)
{
if (!_dos_getdiskfree(toupper(*argv[0]) - '@', &dtable))
{
nKbytes = (long) dtable.avail_clusters *
(long) dtable.sectors_per_cluster *
(long) dtable.bytes_per_sector /
1024l;
printf("%c: %7u %7u %7u %9lu %5.1f\n",
toupper(*argv[0]),
dtable.sectors_per_cluster * dtable.bytes_per_sector,
dtable.total_clusters,
dtable.avail_clusters,
nKbytes,
((float) dtable.total_clusters - dtable.avail_clusters) /
dtable.total_clusters * 100.0);
}
else
{
printf("Invalid drive specification\n");
}
argv++;
}
return 0;
}
for (drive = 3; drive < 26; drive++)
{
if (bBreak)
break;
if (_dos_getdiskfree(drive, &dtable))
continue;
nKbytes = (long) dtable.avail_clusters *
(long) dtable.sectors_per_cluster *
(long) dtable.bytes_per_sector /
1024l;
printf("%c: %7u %7u %7u %9lu %5.1f\n",
(char) ('@' + drive),
dtable.sectors_per_cluster * dtable.bytes_per_sector,
dtable.total_clusters,
dtable.avail_clusters,
nKbytes,
(float) (((float) dtable.total_clusters - dtable.avail_clusters) /
dtable.total_clusters * 100.0));
}
return 0;
}
char *expand_wildcards(char *s)
{
static struct find_t info;
char wildcard[80];
static char directory[256];
static char filename[256];
unsigned attrib;
char *c1, *c2;
if (s)
{
strcpy(wildcard, s);
strcpy(directory, wildcard);
if ((c1 = strrchr(directory, '/')) != 0 ||
(c2 = strrchr(directory, '\\')) != 0)
{
if (c1 > c2)
c1[1] = '\0';
else
c2[1] = '\0';
}
else
directory[0] = '\0';
if (! strchr(wildcard, '.'))
strcat(wildcard, "*.*");
attrib = _A_NORMAL | _A_SUBDIR | _A_RDONLY;
if (_dos_findfirst(wildcard, attrib, &info) != 0)
return NULL;
while (!strcmp(info.name, ".") || !strcmp(info.name, ".."))
if (_dos_findnext(&info))
return NULL;
}
else
{
if (_dos_findnext(&info) != 0)
return NULL;
}
strcpy(filename, directory);
strcat(filename, info.name);
return filename;
}
char *FindExe(char *Path, char *Name, int *batch)
{
static char ExecLine[256];
struct find_t info;
char wildcard[160];
int i;
unsigned attrib;
char *Ext;
int r;
int HasExt = 0;
*batch = 0;
for (i=0; *Extensions[i].Ext; i++)
Extensions[i].Exists = 0;
if (Path)
{
strcpy(wildcard, Path);
strcat(wildcard, "\\");
}
else
*wildcard = '\0';
strcat(wildcard, Name);
if (! strchr(Name, '.'))
strcat(wildcard, ".*");
else
HasExt = 1;
attrib = _A_NORMAL | _A_SUBDIR | _A_RDONLY;
for (r = _dos_findfirst(wildcard, attrib, &info); !r; r = _dos_findnext(&info))
{
if ((Ext = strchr(info.name, '.')) == 0)
continue;
Ext++;
for (i = 0; *Extensions[i].Ext; i++)
{
if (!stricmp(Extensions[i].Ext, Ext))
{
Extensions[i].Exists = 1;
break;
}
}
}
for (i = 0; *Extensions[i].Ext; i++)
{
if (Extensions[i].Exists)
{
if (*Extensions[i].Prog == '*')
{
*batch = 1;
*ExecLine = '\0';
}
else if (*Extensions[i].Prog)
{
strcpy(ExecLine, Extensions[i].Prog);
strcat(ExecLine, " ");
}
else
*ExecLine = '\0';
if (Path)
strcat(ExecLine, Path);
if (*ExecLine && ExecLine[strlen(ExecLine) - 1] != '\\')
strcat(ExecLine, "\\");
strcat(ExecLine, Name);
if (!HasExt)
{
strcat(ExecLine, ".");
strcat(ExecLine, Extensions[i].Ext);
}
return ExecLine;
}
}
return NULL;
}
char *FindPath(char *s, int *IsBatch)
{
char PathList[256];
char *ExeName;
char *PathElement;
if (strchr(s, '/') || strchr(s, '\\'))
{
return FindExe(NULL, s, IsBatch);
}
strcpy(PathList, ".;");
strcat(PathList, getenv("PATH"));
for (PathElement = strtok(PathList, ";"); PathElement; PathElement = strtok(NULL, ";"))
if ((ExeName = FindExe(PathElement, s, IsBatch)) != 0)
return ExeName;
return NULL;
}
int do_activate(int argc, char **argv)
{
HWND hWnd;
while (argc--)
{
hWnd = FindWindow(NULL, *argv);
if (hWnd)
{
argv++;
BringWindowToTop(hWnd);
if (IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE);
}
else
{
fprintf(stderr, "%s: Window not found\n", argv);
return 1;
}
}
return 0;
}
struct alias
{
struct alias *next;
char *name;
char *text;
int inuse;
};
struct alias *alias_list = NULL;
int do_alias(int argc, char **argv)
{
char *c;
struct alias *Alias;
int i;
int len;
if (argc)
{
if (argc > 1)
{
for (len = 0, i = 1; i < argc; i++)
len += strlen(argv[i]);
len += argc - 1;
Alias = malloc(sizeof(struct alias));
Alias->name = malloc(strlen(argv[0])+1);
Alias->text = malloc(len);
strcpy(Alias->name, argv[0]);
strcpy(Alias->text, argv[1]);
for (i = 2; i < argc; i++)
{
strcat(Alias->text, " ");
strcat(Alias->text, argv[i]);
}
Alias->inuse = 0;
Alias->next = alias_list;
alias_list = Alias;
}
else
{
for (Alias = alias_list; Alias!=NULL; Alias = Alias->next)
{
if (!strcmp(Alias->name, argv[0]))
{
printf("%-10s %s\n", argv[0], Alias->text);
return 0;
}
}
fprintf(stderr, "No such alias: %s\n", argv[0]);
return 1;
}
}
else
{
for (Alias = alias_list; Alias; Alias = Alias->next)
printf("%-10s %s\n", Alias->name, Alias->text);
}
return 0;
}
int do_set(int argc, char **argv)
{
char *word;
char *value, envvar[160];
char *putable;
int i;
char **current;
if (!argc)
{
for (current = environ; *current; current++)
printf("%s\n", *current);
return 0;
}
if (argc > 1)
{
sprintf(envvar, "%s=%s", argv[0], argv[1]);
for (i = 2; i < argc; i++)
{
strcat(envvar, " ");
strcat(envvar, argv[i]);
}
putable = malloc(strlen(envvar)+1);
strcpy(putable, envvar);
if (putenv(putable))
{
fprintf(stderr, "%s: %s\n", putable, sys_errlist[errno]);
free(putable);
}
}
else
{
if ((value = getenv(argv[0])) != 0)
{
printf("%s=%s\n", argv[0], value);
}
else
{
printf("No value for %s\n", argv[0]);
return 1;
}
}
return 0;
}
int do_mkdir(int argc, char **argv)
{
if (!argc)
{
fprintf(stderr, "Must specify a directory for mkdir\n");
return 0;
}
while (!bBreak && argc--)
{
if (mkdir(*argv)==-1)
{
fprintf(stderr, "%s: %s\n", argv[0], sys_errlist[errno]);
return 1;
}
argv++;
}
return 0;
}
int do_rmdir(int argc, char **argv)
{
if (!argc)
{
printf("Must specify a directory for rmdir\n");
return 1;
}
while (!bBreak && argc--)
{
if (rmdir(*argv)==-1)
{
fprintf(stderr, "%s: %s\n", argv[0], sys_errlist[errno]);
return 1;
}
argv++;
}
return 0;
}
int do_del(int argc, char **argv)
{
int files;
char *sfile;
int error;
if (!argc)
{
printf("Must specify files for del\n");
return 1;
}
while (!bBreak && argc--)
{
for (files = 0, sfile = expand_wildcards(argv[0]);
!bBreak && sfile;
files++, sfile = expand_wildcards(NULL))
{
if (unlink(sfile)==-1)
{
fprintf(stderr, "%s: %s\n", sfile, sys_errlist[errno]);
error = 1;
}
}
if (!files)
{
fprintf(stderr, "%s: file not found\n", argv[0]);
error = 1;
}
argv++;
}
return error;
}
int do_type(int argc, char **argv)
{
int files;
char *sfile;
FILE *fp;
char Buffer[512];
int nread;
int error = 0;
if (!argc)
{
fprintf(stderr, "Must specify files for type\n");
return 1;
}
while (!bBreak && argc--)
{
for (files = 0, sfile = expand_wildcards(argv[0]);
!bBreak && sfile;
files++, sfile = expand_wildcards(NULL))
{
if ((fp = fopen(sfile, "r")) == NULL)
{
fprintf(stderr, "%s: %s\n", sfile, sys_errlist[errno]);
error = 1;
continue;
}
while (!bBreak &&
(nread = fread(Buffer, 1, 512, fp)) > 0)
fwrite(Buffer, 1, nread, stdout);
fclose(fp);
}
if (!files)
{
fprintf(stderr, "%s: file not found\n", argv[0]);
error = 1;
}
argv++;
}
return error;
}
#pragma argsused
int do_mem(int argc, char **argv)
{
printf("%ldK free %d%% System Resources free\n",
GetFreeSpace(0) / 1024,
GetFreeSystemResources(GFSR_SYSTEMRESOURCES));
return 0;
}
#pragma argsused
int do_sysinfo(int argc, char **argv)
{
DWORD sys_info;
sys_info = GetWinFlags();
if (sys_info & WF_80x87)
printf("Maths Coprocessor Present\n");
if (sys_info & WF_CPU286)
printf("80286 Processor\n");
if (sys_info & WF_CPU386)
printf("80386 Processor\n");
if (sys_info & WF_CPU486)
printf("i486 Processor\n");
if (sys_info & WF_ENHANCED)
printf("Enhanced Mode\n");
if (sys_info & WF_STANDARD)
printf("Standard Mode\n");
if (sys_info & WF_PAGING)
printf("System has paging\n");
return 0;
}
/*
* ps - list all running tasks with useful info. Note that while we are printing,
* we may process messages. Once this happens, the task list may be in a new order.
* consequently, we must build the list without displaying, and then display the
* results from the list.
*/
extern int tkern_total_zombies(void);
extern int tkern_list_zombies(struct tk_process *, int);
extern int tkern_get_process(HTASK, struct tk_process *);
#pragma argsused
int do_ps(int argc, char **argv)
{
TASKENTRY te;
FARPROC lpfnEnumWndProc;
char TaskName[160];
int nTasks = 0;
int iTask = 0;
TASKENTRY *teList;
char **ppchTaskNames;
struct tk_process *pZombies;
struct tk_process *pProcesses;
int nZombies;
int i;
te.dwSize = sizeof(TASKENTRY);
printf(" PID PPID Task Parent Hinst Events StkSz Command\n");
lpfnEnumWndProc = MakeProcInstance((FARPROC) EnumOldApp, hInstance);
TaskFirst(&te);
do
{
nTasks++;
} while (TaskNext(&te));
pProcesses = (struct tk_process *) malloc(sizeof(*pProcesses) * nTasks);
nZombies = tkern_total_zombies();
if (nZombies)
{
pZombies = (struct tk_process *) malloc(sizeof(*pZombies) * nZombies);
tkern_list_zombies(pZombies, nZombies);
}
teList = (TASKENTRY *) malloc(sizeof(TASKENTRY) * nTasks);
ppchTaskNames = malloc(sizeof(char *) * nTasks);
memset(ppchTaskNames, 0, sizeof(char *) * nTasks);
TaskFirst(&te);
do
{
teList[iTask] = te;
tkern_get_process(te.hTask, &pProcesses[iTask]);
strcpy(TaskName, teList[iTask].szModule);
if (!strcmp(TaskName, "WINOLDAP"))
{
hWndOA = 0;
EnumTaskWindows(teList[iTask].hTask, (WNDENUMPROC) lpfnEnumWndProc, 0L);
if (hWndOA)
GetWindowText(hWndOA, TaskName, 160);
ppchTaskNames[iTask] = malloc(strlen(TaskName) + 1);
strcpy(ppchTaskNames[iTask], TaskName);
}
iTask++;
} while (TaskNext(&te));
for (iTask = 0; iTask < nTasks; iTask++)
{
printf("%5d %5d %5d %5d %5d %5d %4x %s\n",
pProcesses[iTask].pid,
pProcesses[iTask].pidParent,
teList[iTask].hTask,
teList[iTask].hTaskParent,
teList[iTask].hInst,
teList[iTask].wcEvents,
teList[iTask].wStackBottom - teList[iTask].wStackTop,
ppchTaskNames[iTask] ? ppchTaskNames[iTask] : teList[iTask].szModule);
if (ppchTaskNames[iTask])
free(ppchTaskNames[iTask]);
}
free(ppchTaskNames);
free(teList);
free(pProcesses);
FreeProcInstance(lpfnEnumWndProc);
if (nZombies)
{
for (i = 0; i < nZombies; i++)
printf("%5d %5d <defunct>\n",
(int) pZombies[i].pid,
(int) pZombies[i].pidParent);
free(pZombies);
}
return 0;
}
int do_kill(int argc, char **argv)
{
int signal;
char *flags;
int pid;
BOOL bError = FALSE;
if (argc && *argv[0] == '-')
{
signal = atoi(argv[0]+1);
argc--;
argv++;
}
else
signal = 14;
if (!argc)
{
printf("Usage: kill [-#] task\n");
return 1;
}
do
{
pid = atoi(argv[0]);
if (kill(pid, signal) == -1)
fprintf(stderr, "%d: %s\n", pid, sys_errlist[errno]);
argv++;
} while (--argc);
return bError;
}
#pragma argsused
int do_date(int argc, char **argv)
{
long tm;
time(&tm);
printf("%s", ctime(&tm));
return 0;
}
int do_mv(int argc, char **argv)
{
char *dest;
struct stat sbuf;
char TmpBuffer[160];
char *FileStart;
char *sfile;
int files;
int error = 0;
if ((argc > 2 && (stat(argv[argc-1], &sbuf) == -1 ||
!(sbuf.st_mode & S_IFDIR))) ||
argc < 2)
{
fprintf(stderr, "Usage: mv file1 file2\n mv files directory\n");
return 1;
}
dest = argv[argc-1];
argc--;
if (strlen(dest) == 2 && dest[1] == ':')
{
strcpy(TmpBuffer, dest);
strcat(TmpBuffer, ".\\");
dest = TmpBuffer;
FileStart = TmpBuffer + strlen(TmpBuffer);
}
else if (stat(dest, &sbuf) != -1 && sbuf.st_mode & S_IFDIR)
{
strcpy(TmpBuffer, dest);
if (TmpBuffer[strlen(TmpBuffer)-1] != '\\')
strcat(TmpBuffer, "\\");
FileStart = TmpBuffer + strlen(TmpBuffer);
dest = TmpBuffer;
}
else
FileStart = NULL;
while (!bBreak && argc--)
{
for (files = 0, sfile = expand_wildcards(argv[0]);
!bBreak && sfile;
files++, sfile = expand_wildcards(NULL))
{
if (FileStart)
strcpy(FileStart, BaseName(sfile));
if (rename(sfile, dest) == -1)
{
fprintf(stderr, "%s: %s\n", sfile, sys_errlist[errno]);
error = 1;
}
}
if (!files)
{
fprintf(stderr, "%s: File not found\n", argv[0]);
error = 1;
}
argv++;
}
return error;
}
int do_exit(int argc, char **argv)
{
if (argc)
exit(atoi(argv[0]));
else
exit(0);
return -1;
}
int do_copy(int argc, char **argv)
{
char *dest;
struct stat sbuf;
char TmpBuffer[160];
char Buffer[512];
char *FileStart;
char *sfile;
int files;
int fdin, fdout;
int nread;
char far *lpchBuffer;
HANDLE hMem;
unsigned uDate, uTime;
int error = 0;
if ((argc > 2 && (stat(argv[argc-1], &sbuf) == -1 ||
!(sbuf.st_mode & S_IFDIR))) ||
argc < 2)
{
fprintf(stderr, "Usage: copy file1 file2\n copy files directory\n");
return 1;
}
dest = argv[argc-1];
argc--;
if (strlen(dest) == 2 && dest[1] == ':')
{
strcpy(TmpBuffer, dest);
strcat(TmpBuffer, ".\\");
dest = TmpBuffer;
FileStart = TmpBuffer + strlen(TmpBuffer);
}
else if (stat(dest, &sbuf) != -1 && sbuf.st_mode & S_IFDIR)
{
strcpy(TmpBuffer, dest);
if (TmpBuffer[strlen(TmpBuffer)-1] != '\\')
strcat(TmpBuffer, "\\");
FileStart = TmpBuffer + strlen(TmpBuffer);
dest = TmpBuffer;
}
else
FileStart = NULL;
hMem = GlobalAlloc(GMEM_FIXED, 32000);
lpchBuffer = GlobalLock(hMem);
while (!bBreak && argc--)
{
for (files = 0, sfile = expand_wildcards(argv[0]);
!bBreak && sfile;
files++, sfile = expand_wildcards(NULL))
{
if (FileStart)
strcpy(FileStart, BaseName(sfile));
if ((fdin = _lopen(sfile, READ)) == -1)
{
fprintf(stderr, "Cannot open %s: %s\n", sfile, sys_errlist[errno]);
error = 1;
continue;
}
if ((fdout = _lcreat(dest, 0)) == -1)
{
_lclose(fdin);
fprintf(stderr, "Cannot create %s: %s\n", dest, sys_errlist[errno]);
error = 1;
continue;
}
while (!bBreak && (nread = _lread(fdin, lpchBuffer, 32000)) != 0)
_lwrite(fdout, lpchBuffer, nread);
_dos_getftime(fdin, &uDate, &uTime);
_dos_setftime(fdout, uDate, uTime);
_lclose(fdin);
_lclose(fdout);
if (bBreak)
unlink(dest);
}
if (!files)
{
fprintf(stderr, "%s: File not found\n", argv[0]);
error = 1;
}
argv++;
}
GlobalUnlock(hMem);
GlobalFree(hMem);
return error;
}
int do_echo(int argc, char **argv)
{
while (argc--)
printf("%s ", *argv++);
printf("\n");
return 0;
}
#pragma argsused
int
do_true(int argc,
char **argv)
{
return 0;
}
#pragma argsused
int
do_false(int argc,
char **argv)
{
return 1;
}
struct
{
char *name;
int (*func)(int argc, char **argv);
} command_list[] = {
":", do_true,
"ACTIVATE", do_activate,
"ALIAS", do_alias,
"CD", do_cd,
"COPY", do_copy,
"DATE", do_date,
"DEL", do_del,
"DF", do_df,
"DIR", do_dos_dir,
"ECHO", do_echo,
"EXIT", do_exit,
"FALSE", do_false,
"KILL", do_kill,
"LS", do_dir,
"MEM", do_mem,
"MKDIR", do_mkdir,
"MV", do_mv,
"PS", do_ps,
"PWD", do_pwd,
"RMDIR", do_rmdir,
"SET", do_set,
"SYSINFO", do_sysinfo,
"TRUE", do_true,
"TYPE", do_type,
0, 0
};
#pragma argsused
int RunBatch(char *FileName, char **argv, int argc)
{
FILE *fp;
char buf[2048];
if ((fp = fopen(FileName, "r")) == 0)
{
while (!bBreak && fgets(buf, 2048, fp))
{
buf[strlen(buf)-1] = '\0';
parse_command(buf);
}
fclose(fp);
return 0;
}
else
{
printf("%s: %s\n", FileName, sys_errlist[errno]);
return -1;
}
}
int expand_alias(char const *cmd, char const *args, int *retval)
{
char *expanded;
struct alias *Alias;
for (Alias = alias_list; Alias; Alias=Alias->next)
{
if (!stricmp(Alias->name, cmd))
{
if (Alias->inuse)
{
/* Allow an alias to merely add arguments */
return FALSE;
}
expanded = malloc(strlen(Alias->text)+
strlen(args)+2);
strcpy(expanded, Alias->text);
if (args)
{
strcat(expanded, " ");
strcat(expanded, args);
}
Alias->inuse = 1;
*retval = parse_command(expanded);
Alias->inuse = 0;
free(expanded);
return TRUE;
}
}
return FALSE;
}
int do_command( char **orig_args,
int nArgs,
BOOL bWait,
BOOL bPipe,
struct redirection *ar,
int nRedirections)
{
char **args, **alloc_args;
int ret;
int i;
int iTask;
char *PathElement;
char *ExeName;
char Command[256];
HTASK hTask;
int GotTask;
int IsBatch;
HWND focus;
long wstatus;
int fdSource[3];
if (!nArgs)
return 0; /* Null command always succeeds */
args = alloc_args = malloc(sizeof(*args) * (nArgs + 1));
memcpy(args, orig_args, sizeof(*args) * (nArgs + 1));
/* Check for a drive change directive */
if (nArgs == 1 &&
(strlen(args[0]) == 2) &&
(args[0][1] == ':')) // Change Drive:
return do_chdrive(args[0]);
/* Check for builtin commands */
for (i = 0; command_list[i].name; i++)
if (!stricmp(command_list[i].name, args[0]))
return (*command_list[i].func)(nArgs-1, args+1);
NewDead = 0;
strcpy(tmpbuf, ".;");
strcat(tmpbuf, getenv("PATH"));
strupr(args[0]);
if ((ExeName = FindPath(args[0], &IsBatch)) != 0)
{
if (IsBatch)
{
ret = RunBatch(ExeName, args+1, nArgs-1);
}
else
{
*Command = 0;
while (--nArgs)
{
if (*Command)
strcat(Command, " ");
++args;
if (strchr(*args, ' ') ||
strchr(*args, '\t'))
{
strcat(Command, "\"");
strcat(Command, *args);
strcat(Command, "\"");
}
else
strcat(Command, *args);
}
for (i = 0; i < nRedirections; i++)
{
if (ar[i].fdSource != -1)
{
fdSource[i] = dup(ar[i].fdSource);
if (fdSource[i] == -1)
fprintf(stderr, "%d: %s\n",
ar[i].fdSource,
sys_errlist[errno]);
}
else
{
fdSource[i] = open( ar[i].pchFile,
ar[i].iMode,
0666);
if (fdSource[i] == -1)
fprintf(stderr, "%s: %s\n",
ar[i].pchFile,
sys_errlist[errno]);
}
if (fdSource[i] == -1)
{
while (i > 0)
close(fdSource[--i]);
free(alloc_args);
return -1;
}
}
iTask = fork();
switch(iTask)
{
case 0:
for (i = 0; i < nRedirections; i++)
{
if (dup2(fdSource[i], ar[i].fd) == -1)
{
fprintf(stderr, "dup2: %s\n", sys_errlist[errno]);
}
close(fdSource[i]);
}
execv_ext(Command, ExeName, orig_args);
break;
case -1:
fprintf(stderr, "%s: %s\n", ExeName, sys_errlist[errno]);
ret = -1;
break;
default:
if (bWait)
{
waitpid(iTask, &wstatus, 0);
if (WIFEXITED(wstatus))
ret = WEXITSTATUS(wstatus);
else
ret = -1;
}
else if (bPipe)
{
add_backend(iTask);
ret = 0;
}
else
{
ret = 0;
}
break;
}
for (i = 0; i < nRedirections; i++)
{
close(fdSource[i]);
}
}
}
else
{
ret = -2;
fprintf(stderr, "%s: File not found\n", args[0]);
}
free(alloc_args);
return ret;
}
char const *FindMatch(char const *buffer, char match)
{
for (buffer++; *buffer; buffer++)
{
if (*buffer == match)
return buffer;
if (*buffer == '\\' && buffer[1])
buffer++;
}
return 0;
}
BOOL IsEscapable(char c)
{
return (c == '\\' || c == '\'' || c == '"' ||
c == ';' || c == ' ' || c == '\t');
}
#define ARG_CHUNK 64
#define CALC_SIZE(x) (((x)-1)-((x)-1)%ARG_CHUNK+ARG_CHUNK)
#pragma argsused
void CopyTo(char **arg, char const *data, int chars, int dosubs)
{
int len;
int size;
int newlen;
int newsize;
char *newarg;
if (!*arg)
{
size = 0;
len = 1;
}
else
{
len = strlen(*arg) + 1;
size = CALC_SIZE(len);
}
newlen = len + chars;
newsize = CALC_SIZE(newlen);
if (newsize != size)
{
newarg = malloc(newsize);
if (*arg)
{
memcpy(newarg, arg, len);
free(*arg);
}
*arg = newarg;
}
memcpy(*arg + len - 1, data, chars);
(*arg)[newlen-1] = '\0';
}
void FreeArgs(char **args, int nArgs)
{
int i;
for (i = 0; i < nArgs; i++)
{
free(args[i]);
args[i] = 0;
}
}
void FinishArg(char **arg)
{
int len;
int size;
char *newarg;
len = strlen(*arg) + 1;
size = CALC_SIZE(len);
if (size == len)
return;
newarg = malloc(len);
memcpy(newarg, *arg, len);
free(*arg);
*arg = newarg;
}
#define TOKEN_ENDCOMMAND ((unsigned) 0x8001)
#define TOKEN_BGCOMMAND ((unsigned) 0x8002)
#define TOKEN_REDIRFROM ((unsigned) 0x8003)
#define TOKEN_REDIRTO ((unsigned) 0x8004)
#define TOKEN_APPENDTO ((unsigned) 0x8005)
#define TOKEN_FDFROM ((unsigned) 0x8006)
#define TOKEN_FDTO ((unsigned) 0x8007)
#define TOKEN_PIPE ((unsigned) 0x8008)
#define TOKEN_SPECIAL ((unsigned) 0x8000)
#define TOKEN_ERROR ((unsigned) 0xFFFF)
#define TOKEN_NONE ((unsigned) 0x0000)
#define TOKEN_OK ((unsigned) 0x0001)
static char const achTokenChars[] =
{ ";&<>|" };
struct token_information
{
char *pchToken;
int nToken;
};
static struct token_information ati[] =
{
{ ">&", TOKEN_FDTO },
{ "<&", TOKEN_FDFROM },
{ ">>", TOKEN_APPENDTO },
{ ">", TOKEN_REDIRTO },
{ "<", TOKEN_REDIRFROM },
{ "&", TOKEN_BGCOMMAND },
{ ";", TOKEN_ENDCOMMAND },
{ "|", TOKEN_PIPE },
{ 0, 0 }
};
unsigned GetArg(char const **pchString,
char **arg,
BOOL *bRunOn)
{
int i;
int nLen;
char const *c;
char const *end;
*bRunOn = FALSE;
c = *pchString;
while (isspace(*c))
c++;
if (!*c)
{
*bRunOn = FALSE;
return TOKEN_NONE;
}
if (strchr(achTokenChars, *c))
{
*bRunOn = FALSE;
for (i = 0; ati[i].nToken; i++)
{
nLen = strlen(ati[i].pchToken);
if (!strncmp(ati[i].pchToken, c, nLen))
{
*pchString = c + nLen;
return ati[i].nToken;
}
}
/* It is impossible to get here */
*(char *) 0 = 0;
}
for (; *c!='\0'; c++)
{
if (isspace(*c))
{
FinishArg(arg);
*bRunOn = FALSE;
*pchString = c;
return TOKEN_OK;
}
if (strchr(achTokenChars, *c))
{
*bRunOn = TRUE;
FinishArg(arg);
*pchString = c;
return TOKEN_OK;
}
switch(*c)
{
case '"':
case '\'':
end = FindMatch(c, *c);
if (!end)
{
fprintf(stderr, "Unterminated %c\n", *c);
if (*arg)
{
free(*arg);
*arg = 0;
}
return TOKEN_ERROR;
}
CopyTo(arg, c+1, end - c - 1, (*c == '"'));
c = end;
break;
case '\\':
if (IsEscapable(c[1]))
{
CopyTo(arg, ++c, 1, 0);
break;
}
default:
CopyTo(arg, c, 1, 0);
break;
}
}
*bRunOn = FALSE;
*pchString = c;
FinishArg(arg);
return TOKEN_OK;
}
void free_redirections( struct redirection *ar,
int nRedirections)
{
int i;
for (i = 0; i < nRedirections; i++)
{
if (ar[i].pchFile)
free(ar[i].pchFile);
}
}
void cleanup( char *pchArg,
char **ppchArgs,
int nUsed,
struct redirection *ar,
int nRedirections,
int pfd[2])
{
if (pchArg)
free(pchArg);
FreeArgs(ppchArgs, nUsed);
free(ppchArgs);
free_redirections(ar, nRedirections);
if (pfd[0] != -1)
close(pfd[0]);
}
int parse_command( char const *pchCmd)
{
char *c, *c2, *end;
char **args;
char *pchArg;
int nUsed;
int fdNow;
int i;
int retval;
struct redirection ar[3];
int nRedirections = 0;
unsigned nToken, nFileToken;
BOOL bRunOn = FALSE;
BOOL bLastRunOn;
BOOL bNonDigit;
int nFile;
int pfd[2];
int fdOldPipe;
pfd[0] = pfd[1] = -1;
args = malloc(50 * sizeof(char *));
memset(args, 0, sizeof(*args) * 50);
nUsed = 0;
while(!bBreak)
{
bLastRunOn = bRunOn;
pchArg = 0;
nToken = GetArg(&pchCmd, &pchArg, &bRunOn);
switch (nToken)
{
case TOKEN_NONE:
case TOKEN_ENDCOMMAND:
case TOKEN_BGCOMMAND:
case TOKEN_PIPE:
if (nUsed)
{
fdOldPipe = pfd[0];
if (nToken == TOKEN_PIPE)
{
for (i = 0; i < nRedirections; i++)
{
if (ar[i].fd == 1)
{
fprintf(stderr, "Ambiguous redirection\n");
cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
return -1;
}
}
if (pipe(pfd) == -1)
{
fprintf(stderr, "pipe: %s\n", sys_errlist[errno]);
cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
return -1;
}
ar[nRedirections].fd = 1;
ar[nRedirections].fdSource = pfd[1];
ar[nRedirections].pchFile = 0;
nRedirections++;
}
else
{
pfd[0] = pfd[1] = -1;
}
retval = do_command(args, nUsed,
(nToken == TOKEN_BGCOMMAND ||
nToken == TOKEN_PIPE) ?
FALSE : TRUE,
(nToken == TOKEN_PIPE) ?
TRUE : FALSE,
ar, nRedirections);
FreeArgs(args, nUsed);
nUsed = 0;
free_redirections(ar, nRedirections);
nRedirections = 0;
if (nToken == TOKEN_PIPE)
{
close(pfd[1]);
ar[nRedirections].fd = 0;
ar[nRedirections].fdSource = pfd[0];
ar[nRedirections].pchFile = 0;
nRedirections++;
}
if (fdOldPipe != -1)
close(fdOldPipe);
}
else
{
FreeArgs(args, nUsed);
free(args);
free_redirections(ar, nRedirections);
return retval;
}
break;
case TOKEN_OK:
args[nUsed++] = pchArg;
if (nUsed == 1 &&
expand_alias(args[0], pchCmd, &retval))
{
FreeArgs(args, nUsed);
free(args);
free_redirections(ar, nRedirections);
return retval;
}
break;
case TOKEN_FDTO:
case TOKEN_APPENDTO:
case TOKEN_REDIRTO:
case TOKEN_REDIRFROM:
case TOKEN_FDFROM:
nFileToken = GetArg(&pchCmd, &pchArg, &bRunOn);
if (nFileToken != TOKEN_OK)
{
fprintf(stderr, "Redirection syntax error\n");
cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
return -1;
}
bRunOn = FALSE;
nFile = -1;
if (bLastRunOn)
{
bNonDigit = FALSE;
for (i = 0; args[nUsed - 1][i]; i++)
{
if (!isdigit(args[nUsed - 1][i]))
{
bNonDigit = TRUE;
break;
}
}
if (!bNonDigit && args[nUsed - 1][0])
{
nFile = atoi(args[nUsed - 1]);
free(args[--nUsed]);
args[nUsed] = 0;
if (nFile > 2)
{
fprintf(stderr, "Silly redirection\n");
cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
return -1;
}
}
}
if (nFile == -1)
{
switch(nToken)
{
case TOKEN_FDTO:
case TOKEN_APPENDTO:
case TOKEN_REDIRTO:
nFile = 1;
break;
case TOKEN_REDIRFROM:
case TOKEN_FDFROM:
nFile = 2;
break;
}
}
for (i = 0; i < nRedirections; i++)
{
if (ar[i].fd == nFile)
{
fprintf(stderr, "Ambiguous redirection\n");
cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
return -1;
}
}
ar[nRedirections].fd = nFile;
switch(nToken)
{
case TOKEN_FDFROM:
case TOKEN_FDTO:
ar[nRedirections].pchFile = 0;
ar[nRedirections].fdSource = atoi(pchArg);
free(pchArg);
break;
case TOKEN_APPENDTO:
case TOKEN_REDIRTO:
case TOKEN_REDIRFROM:
ar[nRedirections].pchFile = pchArg;
ar[nRedirections].fdSource = -1;
break;
}
switch(nToken)
{
case TOKEN_REDIRFROM:
case TOKEN_FDFROM:
ar[nRedirections].iMode = O_RDONLY;
break;
case TOKEN_REDIRTO:
case TOKEN_FDTO:
ar[nRedirections].iMode = O_WRONLY | O_CREAT | O_TRUNC;
break;
case TOKEN_APPENDTO:
ar[nRedirections].iMode = O_WRONLY | O_CREAT | O_APPEND;
break;
}
nRedirections++;
break;
case TOKEN_ERROR:
cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
return -1;
}
}
cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
return -1;
}